package com.purchase.service.impl;

import com.purchase.entity.AppUser;
import com.purchase.entity.Coupon;
import com.purchase.entity.GoodsStock;
import com.purchase.entity.WxUser;
import com.purchase.mapper.*;
import com.purchase.service.AccountHandleService;
import com.purchase.service.PayService;
import com.purchase.util.*;
import com.purchase.util.wxpay.app.SignValidUtilAPP;
import com.purchase.util.wxpay.app.WxPayAESUtilAPP;
import com.purchase.util.wxpay.jsapi.SignValidUtil;
import com.purchase.util.wxpay.WXPayUtil;
import com.purchase.util.wxpay.app.WxpayHandlerAPP;
import com.purchase.util.wxpay.jsapi.WxPayAESUtil;
import com.purchase.util.wxpay.jsapi.WxpayHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.math.BigDecimal;
import java.util.*;

@Slf4j
@Service
public class PayServiceImpl implements PayService {

	@Autowired
	private AppUserMapper appUserMapper;

	@Autowired
	private WxpayHandler wxpayHandler;

	@Autowired
	private WxpayHandlerAPP wxpayHandlerAPP;

	@Autowired
	private OrderMapper orderMapper;

	@Autowired
	private PayMapper payMapper;

	@Autowired
	private GoodsStockMapper goodsStockMapper;

	@Autowired
	private WxUserMapper wxUserMapper;

	@Autowired
	private CouponMapper couponMapper;

//	@Autowired
//	MemberCouponsMapper memberCouponsMapper;

	@Resource
	AccountHandleService accountHandleService;

	@Override
	public ResponseForm doUnifiedOrder(RequestForm param) {
		log.info("发起下单 - 开始");
		ResponseForm result = new ResponseForm();
		Map<String, String> paramMap = (Map<String, String>) param.getData();
		String orderId = null;
		try {
			String wxUid = paramMap.get("wxuid");
			orderId = paramMap.get("orderId");
			String contacts = paramMap.get("contacts");
			String mobilePhone = paramMap.get("mobilePhone");
			String detailedAddress = paramMap.get("detailedAddress");
			String tradeType = paramMap.get("tradeType");
			tradeType = null == tradeType ? "JSAPI" : tradeType;
			if (!StringUtils.isNotBlank(wxUid) || !StringUtils.isNotBlank(orderId) || !StringUtils.isNotBlank(contacts)
					|| !StringUtils.isNotBlank(mobilePhone) || !StringUtils.isNotBlank(detailedAddress)
					|| !StringUtils.isNotBlank(tradeType)) {
				result.setStatus(false);
				result.setMessage(LogInfo.PARAM_ERROR);
				log.error(LogInfo.PARAM_ERROR);
				return result;
			}

			// 校验库存
			List<Object> stockList = this.getStockList(orderId);
			if (stockList != null && stockList.size() != 0) {
				Map<String, Object> stockListMap = new HashMap<>();
				stockListMap.put("stockList", stockList);
				result.setData(stockListMap);
				return result;
			}
			
			// 保存收货地址信息到订单
			orderMapper.saveOrderAddress(orderId, contacts, mobilePhone, detailedAddress);

			String openid = "";
			if ("APP".equals(tradeType)) {
				AppUser appUser = new AppUser();
				appUser.setWxUid(wxUid);
				openid = appUser.getOpenId();
			} else if ("JSAPI".equals(tradeType)) {
				WxUser wxUser = new WxUser();
				wxUser.setWxUid(wxUid);
				wxUser = wxUserMapper.selectOne(wxUser);
				openid = wxUser.getOpenId();
			}

			// 组装支付信息
			Map<String, Object> payMap = new HashMap<>();
			Map<String, Object> payOrder = payMapper.getUPayOrderByOrderId(orderId);
			String id;
			if (payOrder != null) {
				// 因为优惠券修改流水金额原因注释以下代码，并添加新流程：如果有已存在的订单关联的流水则删掉
				// //如果已存在该笔订单对应的未支付流水，则使用此流水继续支付
				// id = String.valueOf(payOrder.get("id"));
				// payMap.put("id", payOrder.get("id"));
				// payMap.put("orderId", orderId);
				// payMap.put("totalFee", payOrder.get("total_fee"));
				// payMap.put("goodsBody", payOrder.get("goods_body"));
				// payMap.put("openid", payOrder.get("openid"));
				// payMap.put("tradeType", tradeType);
				payMapper.delPayOrderByOrderId(orderId);
			}

			// 如果新的订单则生成新的流水
			Map<String, Object> order = orderMapper.getWaitPayOrderPriceByIdForPay(orderId);
			Map<String, Object> orderByIdAndStoreNo = orderMapper.getOrderByIdAndStoreNo(orderId, null);
			if ("Q".equals(orderByIdAndStoreNo.get("order_status"))) {
				result.setStatus(true);
				result.setCode("500");
				result.setMessage("订单已过期");
				log.error("订单已过期error,orderId=" + orderId);
				return result;
			}
			id = OrderIdGenerater.generatePayOrderId();
			payMap.put("id", id);
			payMap.put("orderId", orderId);
			payMap.put("totalFee", order.get("totalFee"));
			payMap.put("goodsBody", "叮代购" + orderId);
			payMap.put("openid", openid);
			payMap.put("tradeType", tradeType);

			// 入库流水
			log.debug("入库流水" + id);
			payMapper.savePayOrder(payMap);

			// 调用微信支付统一下单
			log.debug("调用微信支付统一下单");
			Map<String, String> map = null;
			if ("JSAPI".equals(tradeType)) {
				orderMapper.updateOrderTradeType(orderId, "JSAPI");
				map = wxpayHandler.doUnifiedOrder(payMap);
			} else if ("APP".equals(tradeType)) {
				orderMapper.updateOrderTradeType(orderId, "APP");
				map = wxpayHandlerAPP.doUnifiedOrder(payMap);
			}
			log.debug("微信支付统一下单返回:{}", map);

			HashMap<String, Object> updMap = new HashMap<>();
			updMap.put("prepayId", map.get("prepay_id"));
			updMap.put("id", id);
			payMapper.modifyPayOrder(updMap);
			result.setData(map);
		} catch (Exception e) {
			result.setStatus(false);
			result.setMessage(LogInfo.ERROR);
			log.error("支付下单error,orderId=" + orderId, e);
		}
		return result;
	}

	@Override
	public ResponseForm doUnifiedOrderForGiftPack(RequestForm param) {
		log.info("发起下单 - 开始");
		ResponseForm result = new ResponseForm();
		Map<String, String> paramMap = (Map<String, String>) param.getData();
		String orderId = null;
		try {
			String wxUid = paramMap.get("wxuid");
			orderId = paramMap.get("orderId");
			// String contacts = paramMap.get("contacts");
			// String mobilePhone = paramMap.get("mobilePhone");
			// String detailedAddress = paramMap.get("detailedAddress");
			String tradeType = paramMap.get("tradeType");
			tradeType = null == tradeType ? "JSAPI" : tradeType;
			// if (!StringUtils.isNotBlank(wxUid) || !StringUtils.isNotBlank(orderId) ||
			// !StringUtils.isNotBlank(contacts)
			// || !StringUtils.isNotBlank(mobilePhone) ||
			// !StringUtils.isNotBlank(detailedAddress)
			// || !StringUtils.isNotBlank(tradeType)) {
			// result.setStatus(false);
			// result.setMessage(LogInfo.PARAM_ERROR);
			// log.error(LogInfo.PARAM_ERROR);
			// return result;
			// }

			// // 保存收货地址信息到订单
			// orderMapper.saveOrderAddress(orderId, contacts, mobilePhone,
			// detailedAddress);

			String openid = "";
			if ("APP".equals(tradeType)) {
				AppUser appUser = new AppUser();
				appUser.setWxUid(wxUid);
				openid = appUser.getOpenId();
			} else if ("JSAPI".equals(tradeType)) {
				WxUser wxUser = new WxUser();
				wxUser.setWxUid(wxUid);
				wxUser = wxUserMapper.selectOne(wxUser);
				openid = wxUser.getOpenId();
			}

			// 组装支付信息
			Map<String, Object> payMap = new HashMap<>();
			Map<String, Object> payOrder = payMapper.getUPayOrderByOrderId(orderId);
			String id;
			if (payOrder != null) {
				// 因为优惠券修改流水金额原因注释以下代码，并添加新流程：如果有已存在的订单关联的流水则删掉
				// //如果已存在该笔订单对应的未支付流水，则使用此流水继续支付
				// id = String.valueOf(payOrder.get("id"));
				// payMap.put("id", payOrder.get("id"));
				// payMap.put("orderId", orderId);
				// payMap.put("totalFee", payOrder.get("total_fee"));
				// payMap.put("goodsBody", payOrder.get("goods_body"));
				// payMap.put("openid", payOrder.get("openid"));
				// payMap.put("tradeType", tradeType);
				payMapper.delPayOrderByOrderId(orderId);
			}

			// 如果新的订单则生成新的流水
			Map<String, Object> order = orderMapper.getWaitPayOrderPriceByIdForPay(orderId);

			Map<String, Object> orderByIdAndStoreNo = orderMapper.getOrderByIdAndStoreNo(orderId, null);
			if ("Q".equals(orderByIdAndStoreNo.get("order_status"))) {
				result.setStatus(true);
				result.setCode("500");
				result.setMessage("订单已过期");
				log.error("订单已过期error,orderId=" + orderId);
				return result;
			}
			id = OrderIdGenerater.generatePayOrderId();// 生成pay流水id
			payMap.put("id", id);
			payMap.put("orderId", orderId);
			payMap.put("totalFee", order.get("totalFee"));
			payMap.put("goodsBody", "代购大礼包" + orderId);
			payMap.put("openid", openid);
			payMap.put("tradeType", tradeType);
			payMap.put("orderType", orderByIdAndStoreNo.get("order_type"));
			// 入库流水
			log.debug("入库流水" + id);
			payMapper.savePayOrder(payMap);

			// 调用微信支付统一下单
			log.debug("调用微信支付统一下单");
			Map<String, String> map = null;
			// if ("JSAPI".equals(tradeType)) {
			// orderMapper.updateOrderTradeType(orderId, "JSAPI");
			// map = wxpayHandler.doUnifiedOrder(payMap);
			// } else
			if ("APP".equals(tradeType)) {
				orderMapper.updateOrderTradeType(orderId, "APP");
				map = wxpayHandlerAPP.doUnifiedOrder(payMap);
			}
			log.debug("微信支付统一下单返回:{}", map);

			HashMap<String, Object> updMap = new HashMap<>();
			updMap.put("prepayId", map.get("prepay_id"));
			updMap.put("id", id);
			payMapper.modifyPayOrder(updMap);
			result.setData(map);
		} catch (Exception e) {
			result.fail("400", "支付下单error,orderId=" + orderId);
			log.error("支付下单error,orderId=" + orderId, e);
		}
		return result;
	}

	@Override
	public ResponseForm doUnifiedOrderForRechargeMember(RequestForm param) {
		log.info("发起下单 - 开始");
		ResponseForm result = new ResponseForm();
		Map<String, String> paramMap = (Map<String, String>) param.getData();
		String orderId = null;
		try {
			String wxUid = paramMap.get("wxuid");
			orderId = paramMap.get("orderId");
			// String contacts = paramMap.get("contacts");
			// String mobilePhone = paramMap.get("mobilePhone");
			// String detailedAddress = paramMap.get("detailedAddress");
			String tradeType = paramMap.get("tradeType");
			tradeType = null == tradeType ? "JSAPI" : tradeType;
			// if (!StringUtils.isNotBlank(wxUid) || !StringUtils.isNotBlank(orderId) ||
			// !StringUtils.isNotBlank(contacts)
			// || !StringUtils.isNotBlank(mobilePhone) ||
			// !StringUtils.isNotBlank(detailedAddress)
			// || !StringUtils.isNotBlank(tradeType)) {
			// result.setStatus(false);
			// result.setMessage(LogInfo.PARAM_ERROR);
			// log.error(LogInfo.PARAM_ERROR);
			// return result;
			// }

			// // 保存收货地址信息到订单
			// orderMapper.saveOrderAddress(orderId, contacts, mobilePhone,
			// detailedAddress);

			String openid = "";
			if ("APP".equals(tradeType)) {
				AppUser appUser = new AppUser();
				appUser.setWxUid(wxUid);
				openid = appUser.getOpenId();
			} else if ("JSAPI".equals(tradeType)) {
				WxUser wxUser = new WxUser();
				wxUser.setWxUid(wxUid);
				wxUser = wxUserMapper.selectOne(wxUser);
				openid = wxUser.getOpenId();
			}

			// 组装支付信息
			Map<String, Object> payMap = new HashMap<>();
			Map<String, Object> payOrder = payMapper.getUPayOrderByOrderId(orderId);
			String id;
			if (payOrder != null) {
				// 因为优惠券修改流水金额原因注释以下代码，并添加新流程：如果有已存在的订单关联的流水则删掉
				// //如果已存在该笔订单对应的未支付流水，则使用此流水继续支付
				// id = String.valueOf(payOrder.get("id"));
				// payMap.put("id", payOrder.get("id"));
				// payMap.put("orderId", orderId);
				// payMap.put("totalFee", payOrder.get("total_fee"));
				// payMap.put("goodsBody", payOrder.get("goods_body"));
				// payMap.put("openid", payOrder.get("openid"));
				// payMap.put("tradeType", tradeType);
				payMapper.delPayOrderByOrderId(orderId);
			}

			// 如果新的订单则生成新的流水
			Map<String, Object> order = orderMapper.getWaitPayOrderPriceByIdForPay(orderId);

			Map<String, Object> orderByIdAndStoreNo = orderMapper.getOrderByIdAndStoreNo(orderId, null);
			if ("Q".equals(orderByIdAndStoreNo.get("order_status"))) {
				result.setStatus(true);
				result.setCode("500");
				result.setMessage("订单已过期");
				log.error("订单已过期error,orderId=" + orderId);
				return result;
			}
			id = OrderIdGenerater.generatePayOrderId();// 生成pay流水id
			payMap.put("id", id);
			payMap.put("orderId", orderId);
			payMap.put("totalFee", order.get("totalFee"));
			payMap.put("goodsBody", "会员充值" + orderId);
			payMap.put("openid", openid);
			payMap.put("tradeType", tradeType);
			payMap.put("orderType", orderByIdAndStoreNo.get("order_type"));
			// 入库流水
			log.debug("入库流水" + id);
			payMapper.savePayOrder(payMap);

			// 调用微信支付统一下单
			log.debug("调用微信支付统一下单");
			Map<String, String> map = null;
			if ("JSAPI".equals(tradeType)) {
				orderMapper.updateOrderTradeType(orderId, "JSAPI");
				map = wxpayHandler.doUnifiedOrder(payMap);
			}
			// else if ("APP".equals(tradeType)) {
			// orderMapper.updateOrderTradeType(orderId, "APP");
			// map = wxpayHandlerAPP.doUnifiedOrder(payMap);
			// }
			log.debug("微信支付统一下单返回:{}", map);

			HashMap<String, Object> updMap = new HashMap<>();
			updMap.put("prepayId", map.get("prepay_id"));
			updMap.put("id", id);
			payMapper.modifyPayOrder(updMap);
			result.setData(map);
		} catch (Exception e) {
			result.fail("400", "支付下单error,orderId=" + orderId);
			log.error("支付下单error,orderId=" + orderId, e);
		}
		return result;
	}

	private List<Object> getStockList(String orderId) {
		// 查该笔订单内详情的库存
		List<Map<String, Object>> detailList = orderMapper.getOrderDetailListByOrderId(orderId);
		if (detailList == null) {
			log.error("查询库存error,订单" + orderId + "详情内库存为null");
			return null;
		}
		// 如果商品已下架加到 stockList，另如果库存小于订单内详情数量则将此详情放入一个无货 stockList 并给前端返回 stockList
		List<Object> stockList = new ArrayList<>();
		for (Map<String, Object> detail : detailList) {
			int soldout = (int) detail.get("soldout");
			if (soldout == 1) {
				stockList.add(detail);
			} else if ((int) detail.get("stock_num") < (int) detail.get("goods_num")) {
				stockList.add(detail);
			}
		}
		return stockList;
	}

	@SuppressWarnings({ "unchecked", "rawtypes", "unused" })
	@Transactional(rollbackFor = Exception.class)
	@Override
	public String payNotify(HttpServletRequest request) {
		log.info("接收微信支付结果通知-开始");
		String resXml = "";
		Map resultMap = new HashMap();
		Map payOrderMap = new HashMap();
		Map updOrderMap = new HashMap();
		try {
			// 接收http请求处理
			String notifyXml = HttpClient.reciveHttpReq(request, "微信支付结果通知");

			// xml转map
			Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyXml);
			log.debug("xml to map {}", notifyMap);
			String appid = notifyMap.get("appid");

			// 验签
			if (appid.equals(PropertiesUtil.getValue(PropertiesUtil.WXPATH, "wxpay.appid"))) {
				SignValidUtil.isSignatureValid(notifyMap);
			} else if (appid.equals(PropertiesUtil.getValue(PropertiesUtil.WXPATH, "wxpay.appid.APP"))) {
				SignValidUtilAPP.isSignatureValid(notifyMap);
			}

			// 解析微信xml
			String notifyResultCode = notifyMap.get("result_code");
			String notifyReturnCode = notifyMap.get("return_code");
			String notifyOutTradeNo = notifyMap.get("out_trade_no");
			String notifyTransactionId = notifyMap.get("transaction_id");
			String notifyReturnMsg = notifyMap.get("return_msg");
			String notifyEndTime = notifyMap.get("time_end");
			String notifyTotalFee = notifyMap.get("total_fee");
			log.debug("resultCode=" + notifyResultCode + ",returnCode=" + notifyReturnCode);

			payOrderMap.put("id", notifyOutTradeNo);
			payOrderMap.put("transactionId", notifyTransactionId);
			payOrderMap.put("endTime", notifyEndTime);
			payOrderMap.put("payFailDesc", notifyReturnMsg);

			// 获取库里流水信息
			log.debug("获取库里流水信息");
			Map payOrder = payMapper.getPayOrderById(payOrderMap);
			String orderId = String.valueOf(payOrder.get("order_id"));
			String orderTotalFee = String.valueOf(payOrder.get("total_fee"));
			String payStatus = String.valueOf(payOrder.get("pay_status"));

			// 获取库里订单信息
			log.debug("获取库里订单信息");
			Map<String, Object> order = orderMapper.getOrderByIdAndStoreNo(orderId, null);
			String orderStatus = String.valueOf(order.get("order_status"));

			// 校验订单和流水状态：如果不是待支付W或支付失败则不允许更新状态
			if (!"W".equals(orderStatus) && !"F".equals(orderStatus)) {
				log.debug("订单" + orderId + "已支付");
				resultMap.put("return_msg", "OK");
				resultMap.put("return_code", "SUCCESS");
				resXml = WXPayUtil.mapToXml(resultMap);
				return resXml;
			}

			// 更新流水、订单
			if ("SUCCESS".equals(notifyResultCode) && "SUCCESS".equals(notifyReturnCode)) {

				// 更新流水为成功
				log.debug("更新流水" + notifyOutTradeNo + "为成功");
				payOrderMap.put("payStatus", "S");
				payMapper.modifyPayOrder(payOrderMap);

				// 更新订单为成功
				updOrderMap.put("orderStatus", "S");
				updOrderMap.put("orderId", orderId);
				log.debug("更新订单" + orderId + "为成功");
				orderMapper.updateOrderStatusById(updOrderMap);

				// 更新用户优惠券
				couponMapper.payCoupon(orderId);

				// 计算用户佣金
				String wx_uid = String.valueOf(order.get("wx_uid"));//购买用户的ID
				String order_price = String.valueOf(order.get("price"));//订单应支付金额（会员优惠之后的金额，未使用优惠券前的金额）
				String order_id = String.valueOf(order.get("id"));//订单ID
				String trade_type = String.valueOf(order.get("trade_type"));//小程序端订单或app订单
				accountHandleService.createBonus(wx_uid, order_id, order_price);

				// 校验返回的订单金额是否与商户侧的订单金额一致，防止数据泄漏导致出现“假通知”，造成资金损失
				log.debug("微信返回金额：" + notifyTotalFee);
				log.debug("系统流水金额：" + orderTotalFee);
				if (!notifyTotalFee.equals(yuan2fen(orderTotalFee))) {
					log.error("系统流水金额：" + yuan2fen(orderTotalFee) + "与微信返回金额：" + notifyTotalFee + "不一致，流水号="
							+ notifyOutTradeNo);

					// 更新流水为失败
					log.debug("更新流水" + notifyOutTradeNo + "为失败");
					payOrderMap.put("payStatus", "F");
					payOrderMap.put("payFailDesc",
							"系统流水金额：" + yuan2fen(orderTotalFee) + "与微信返回金额：" + notifyTotalFee + "不一致");
					payMapper.modifyPayOrder(payOrderMap);

					// 更新订单为失败
					log.debug("更新订单" + orderId + "为失败");
					updOrderMap.put("orderStatus", "F");
					updOrderMap.put("orderId", orderId);
					orderMapper.updateOrderStatusById(updOrderMap);

					// 返回微信结果
					resultMap.put("return_code", "FAIL");
					resXml = WXPayUtil.mapToXml(resultMap);
					return resXml;
				}
				log.debug("校验金额一致");
			} else {
				// 更新流水为失败
				log.debug("更新流水为失败");
				payOrderMap.put("payStatus", "F");
				payOrderMap.put("payFailDesc", notifyReturnMsg);
				payMapper.modifyPayOrder(payOrderMap);

				// 更新订单为失败
				log.debug("更新订单为失败");
				updOrderMap.put("orderStatus", "F");
				updOrderMap.put("orderId", orderId);
				orderMapper.updateOrderStatusById(updOrderMap);

				// 还原库存（通过订单里的商品数量修改库存数量）
				restoreGoodsStock(orderId);
				log.debug("已还原库存，订单号=" + orderId);
			}

			// 给微信返回响应报文
			resultMap.put("return_msg", "OK");
			resultMap.put("return_code", "SUCCESS");

		} catch (Exception e) {
			log.error("接收微信支付结果通知error", e);
			resultMap.put("return_code", "FAIL");
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
		}
		try {
			resXml = WXPayUtil.mapToXml(resultMap);
		} catch (Exception e) {
			log.error("接收微信支付结果通知error", e);
		}
		log.info("接收微信支付结果通知-结束-{}", resXml);
		return resXml;
	}

	@SuppressWarnings({ "unchecked", "rawtypes", "unused" })
	@Transactional(rollbackFor = Exception.class)
	@Override
	public String payNotifyForGiftPack(HttpServletRequest request) {
		log.info("接收微信支付结果通知-开始");
		String resXml = "";
		Map resultMap = new HashMap();
		Map payOrderMap = new HashMap();
		Map updOrderMap = new HashMap();
		try {
			// 接收http请求处理
			String notifyXml = HttpClient.reciveHttpReq(request, "微信支付结果通知");

			// xml转map
			Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyXml);
			log.debug("xml to map {}", notifyMap);
			String appid = notifyMap.get("appid");

			// 验签
			if (appid.equals(PropertiesUtil.getValue(PropertiesUtil.WXPATH, "wxpay.appid"))) {
				SignValidUtil.isSignatureValid(notifyMap);
			} else if (appid.equals(PropertiesUtil.getValue(PropertiesUtil.WXPATH, "wxpay.appid.APP"))) {
				SignValidUtilAPP.isSignatureValid(notifyMap);
			}

			// 解析微信xml
			String notifyResultCode = notifyMap.get("result_code");
			String notifyReturnCode = notifyMap.get("return_code");
			String notifyOutTradeNo = notifyMap.get("out_trade_no");
			String notifyTransactionId = notifyMap.get("transaction_id");
			String notifyReturnMsg = notifyMap.get("return_msg");
			String notifyEndTime = notifyMap.get("time_end");
			String notifyTotalFee = notifyMap.get("total_fee");
			log.debug("resultCode=" + notifyResultCode + ",returnCode=" + notifyReturnCode);

			payOrderMap.put("id", notifyOutTradeNo);
			payOrderMap.put("transactionId", notifyTransactionId);
			payOrderMap.put("endTime", notifyEndTime);
			payOrderMap.put("payFailDesc", notifyReturnMsg);

			// 获取库里流水信息
			log.debug("获取库里流水信息");
			Map payOrder = payMapper.getPayOrderById(payOrderMap);
			String orderId = String.valueOf(payOrder.get("order_id"));
			String orderTotalFee = String.valueOf(payOrder.get("total_fee"));
			String payStatus = String.valueOf(payOrder.get("pay_status"));

			// 获取库里订单信息
			log.debug("获取库里订单信息");
			Map<String, Object> order = orderMapper.getOrderByIdAndStoreNo(orderId, null);
			String orderStatus = String.valueOf(order.get("order_status"));

			// 校验订单和流水状态：如果不是待支付W或支付失败则不允许更新状态
			if (!"W".equals(orderStatus) && !"F".equals(orderStatus)) {
				log.debug("订单" + orderId + "已支付");
				resultMap.put("return_msg", "OK");
				resultMap.put("return_code", "SUCCESS");
				resXml = WXPayUtil.mapToXml(resultMap);
				return resXml;
			}

			// 更新流水、订单
			if ("SUCCESS".equals(notifyResultCode) && "SUCCESS".equals(notifyReturnCode)) {

				// 更新流水为成功
				log.debug("更新流水" + notifyOutTradeNo + "为成功");
				payOrderMap.put("payStatus", "S");
				payMapper.modifyPayOrder(payOrderMap);

				// 更新订单为成功
				updOrderMap.put("orderStatus", "S");
				updOrderMap.put("orderId", orderId);
				log.debug("更新订单" + orderId + "为成功");
				orderMapper.updateOrderStatusById(updOrderMap);

				// 更新用户优惠券
				couponMapper.payCoupon(orderId);

				// 校验返回的订单金额是否与商户侧的订单金额一致，防止数据泄漏导致出现“假通知”，造成资金损失
				log.debug("微信返回金额：" + notifyTotalFee);
				log.debug("系统流水金额：" + orderTotalFee);
				if (!notifyTotalFee.equals(yuan2fen(orderTotalFee))) {
					log.error("系统流水金额：" + yuan2fen(orderTotalFee) + "与微信返回金额：" + notifyTotalFee + "不一致，流水号="
							+ notifyOutTradeNo);

					// 更新流水为失败
					log.debug("更新流水" + notifyOutTradeNo + "为失败");
					payOrderMap.put("payStatus", "F");
					payOrderMap.put("payFailDesc",
							"系统流水金额：" + yuan2fen(orderTotalFee) + "与微信返回金额：" + notifyTotalFee + "不一致");
					payMapper.modifyPayOrder(payOrderMap);

					// 更新订单为失败
					log.debug("更新订单" + orderId + "为失败");
					updOrderMap.put("orderStatus", "F");
					updOrderMap.put("orderId", orderId);
					orderMapper.updateOrderStatusById(updOrderMap);

					// 返回微信结果
					resultMap.put("return_code", "FAIL");
					resXml = WXPayUtil.mapToXml(resultMap);
					return resXml;
				}
				log.debug("校验金额一致");
			} else {
				// 更新流水为失败
				log.debug("更新流水为失败");
				payOrderMap.put("payStatus", "F");
				payOrderMap.put("payFailDesc", notifyReturnMsg);
				payMapper.modifyPayOrder(payOrderMap);

				// 更新订单为失败
				log.debug("更新订单为失败");
				updOrderMap.put("orderStatus", "F");
				updOrderMap.put("orderId", orderId);
				orderMapper.updateOrderStatusById(updOrderMap);

				// 还原库存（通过订单里的商品数量修改库存数量）
				restoreGoodsStock(orderId);
				log.debug("已还原库存，订单号=" + orderId);
			}

			// 给微信返回响应报文
			resultMap.put("return_msg", "OK");
			resultMap.put("return_code", "SUCCESS");

			/* 礼包流程:用户身份变更+邀请码生成 */
			String wxUid = (String) order.get("wx_uid");
			AppUser appUser = new AppUser();
			appUser.setWxUid(wxUid);
			appUser = appUserMapper.selectOne(appUser);
			if (appUser != null) {
				System.out.println(
						"用户状态变更了!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
				appUser.setUserStatus(2);
				String inviteCode = InviteCodeUtil.generateAppInviteCode(appUser.getVerifyPhone().substring(8),
						appUser.getWxUid());
				appUser.setInviteCode(inviteCode);
				appUserMapper.updateByPrimaryKeySelective(appUser);
				// 开通代购用户的佣金账户
				accountHandleService.createVendorAccount(appUser);
				//推荐代购奖金计算
				accountHandleService.createVendorAward(appUser, orderId);
			}
			
			//给399礼包代购绑定优惠券
			List<Coupon> memberCoupons = couponMapper.getMemberCoupons(2);
			if (memberCoupons.size() > 0) {
			    List<Map<String, Object>> receivableIdList = new ArrayList<>();
			    for (Coupon memberCoupon : memberCoupons) {
			        HashMap<String, Object> map = new HashMap<>();
			        map.put("wxUid", wxUid);
			        map.put("couponId", memberCoupon.getId());
			        map.put("tradeType", order.get("trade_type"));
			        receivableIdList.add(map);
			    }
			    couponMapper.createCouponUser(receivableIdList);
			}
		} catch (Exception e) {
			log.error("接收微信支付结果通知error", e);
			resultMap.put("return_code", "FAIL");
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
		}
		try {
			resXml = WXPayUtil.mapToXml(resultMap);
		} catch (Exception e) {
			log.error("接收微信支付结果通知error", e);
		}
		log.info("接收微信支付结果通知-结束-{}", resXml);
		return resXml;
	}

	@SuppressWarnings("unchecked")
	@Override
	public String payNotifyForRechargeMember(HttpServletRequest request) {
		log.info("接收微信支付结果通知-开始");
		String resXml = "";
		Map resultMap = new HashMap();
		Map payOrderMap = new HashMap();
		Map updOrderMap = new HashMap();
		try {
			// 接收http请求处理
			String notifyXml = HttpClient.reciveHttpReq(request, "微信支付结果通知");

			// xml转map
			Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyXml);
			log.debug("xml to map {}", notifyMap);
			String appid = notifyMap.get("appid");

			// 验签
			if (appid.equals(PropertiesUtil.getValue(PropertiesUtil.WXPATH, "wxpay.appid"))) {
				SignValidUtil.isSignatureValid(notifyMap);
			} else if (appid.equals(PropertiesUtil.getValue(PropertiesUtil.WXPATH, "wxpay.appid.APP"))) {
				SignValidUtilAPP.isSignatureValid(notifyMap);
			}

			// 解析微信xml
			String notifyResultCode = notifyMap.get("result_code");
			String notifyReturnCode = notifyMap.get("return_code");
			String notifyOutTradeNo = notifyMap.get("out_trade_no");
			String notifyTransactionId = notifyMap.get("transaction_id");
			String notifyReturnMsg = notifyMap.get("return_msg");
			String notifyEndTime = notifyMap.get("time_end");
			String notifyTotalFee = notifyMap.get("total_fee");
			log.debug("resultCode=" + notifyResultCode + ",returnCode=" + notifyReturnCode);

			payOrderMap.put("id", notifyOutTradeNo);
			payOrderMap.put("transactionId", notifyTransactionId);
			payOrderMap.put("endTime", notifyEndTime);
			payOrderMap.put("payFailDesc", notifyReturnMsg);

			// 获取库里流水信息
			log.debug("获取库里流水信息");
			Map payOrder = payMapper.getPayOrderById(payOrderMap);
			String orderId = String.valueOf(payOrder.get("order_id"));
			String orderTotalFee = String.valueOf(payOrder.get("total_fee"));
			String payStatus = String.valueOf(payOrder.get("pay_status"));

			// 获取库里订单信息
			log.debug("获取库里订单信息");
			Map<String, Object> order = orderMapper.getOrderByIdAndStoreNo(orderId, null);
			String orderStatus = String.valueOf(order.get("order_status"));

			// 校验订单和流水状态：如果不是待支付W或支付失败则不允许更新状态
			if (!"W".equals(orderStatus) && !"F".equals(orderStatus)) {
				log.debug("订单" + orderId + "已支付");
				resultMap.put("return_msg", "OK");
				resultMap.put("return_code", "SUCCESS");
				resXml = WXPayUtil.mapToXml(resultMap);
				return resXml;
			}

			// 更新流水、订单
			if ("SUCCESS".equals(notifyResultCode) && "SUCCESS".equals(notifyReturnCode)) {

				// 更新流水为成功
				log.debug("更新流水" + notifyOutTradeNo + "为成功");
				payOrderMap.put("payStatus", "S");
				payMapper.modifyPayOrder(payOrderMap);

				// 更新订单为成功
				updOrderMap.put("orderStatus", "C");
				updOrderMap.put("orderId", orderId);
				updOrderMap.put("logisticStatus", "LS");
				log.debug("更新订单" + orderId + "为成功");
				orderMapper.updateOrderStatusById(updOrderMap);

				// 更新用户优惠券
				couponMapper.payCoupon(orderId);

				// 校验返回的订单金额是否与商户侧的订单金额一致，防止数据泄漏导致出现“假通知”，造成资金损失
				log.debug("微信返回金额：" + notifyTotalFee);
				log.debug("系统流水金额：" + orderTotalFee);
				if (!notifyTotalFee.equals(yuan2fen(orderTotalFee))) {
					log.error("系统流水金额：" + yuan2fen(orderTotalFee) + "与微信返回金额：" + notifyTotalFee + "不一致，流水号="
							+ notifyOutTradeNo);

					// 更新流水为失败
					log.debug("更新流水" + notifyOutTradeNo + "为失败");
					payOrderMap.put("payStatus", "F");
					payOrderMap.put("payFailDesc",
							"系统流水金额：" + yuan2fen(orderTotalFee) + "与微信返回金额：" + notifyTotalFee + "不一致");
					payMapper.modifyPayOrder(payOrderMap);

					// 更新订单为失败
					log.debug("更新订单" + orderId + "为失败");
					updOrderMap.put("orderStatus", "F");
					updOrderMap.put("orderId", orderId);
					orderMapper.updateOrderStatusById(updOrderMap);

					// 返回微信结果
					resultMap.put("return_code", "FAIL");
					resXml = WXPayUtil.mapToXml(resultMap);
					return resXml;
				}
				log.debug("校验金额一致");
			} else {
				// 更新流水为失败
				log.debug("更新流水为失败");
				payOrderMap.put("payStatus", "F");
				payOrderMap.put("payFailDesc", notifyReturnMsg);
				payMapper.modifyPayOrder(payOrderMap);

				// 更新订单为失败
				log.debug("更新订单为失败");
				updOrderMap.put("orderStatus", "F");
				updOrderMap.put("orderId", orderId);
				orderMapper.updateOrderStatusById(updOrderMap);

				// 还原库存（通过订单里的商品数量修改库存数量）
				restoreGoodsStock(orderId);
				log.debug("已还原库存，订单号=" + orderId);
			}

			// 给微信返回响应报文
			resultMap.put("return_msg", "OK");
			resultMap.put("return_code", "SUCCESS");
			try {
				String wxUid = (String) order.get("wx_uid");
				String parentWxuid = (String) order.get("parent_wx_uid");
				/* 礼包流程:小程序用户身份变更 */
				if("JSAPI".equals(order.get("trade_type").toString())) {
					WxUser wxUser = new WxUser();
					wxUser.setWxUid(wxUid);
					wxUser = wxUserMapper.selectOne(wxUser);
					if (wxUser != null) {
						log.debug(
								"小程序用户状态变更了!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
						wxUser.setUserStatus(1);
						wxUser.setParentWxUid(parentWxuid);//绑定会员关系
						wxUserMapper.updateByPrimaryKeySelective(wxUser);
						// 开通小程序端会员的佣金账户（小程序和app用户不通）
						accountHandleService.createMemberAccount(wxUid,parentWxuid,orderId);
						//奖励小程序端推荐人20元佣金
						accountHandleService.createMemberAward(wxUid,parentWxuid,orderId);
					}
				}
				/* 礼包流程:APP用户身份变更 */
				if("APP".equals(order.get("trade_type").toString())) {
					AppUser appUser = new AppUser();
					appUser.setWxUid(wxUid);
					appUser = appUserMapper.selectOne(appUser);
					if (appUser != null) {
						log.debug("APP用户状态变更了!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
						appUser.setUserStatus(1);
						appUserMapper.updateByPrimaryKeySelective(appUser);
						// 开通APP端会员的佣金账户（小程序和app用户不通）
						// accountHandleService.createAccount(appUser);
					}
				}
				
				//给支付成功的会员绑定优惠券
				List<Coupon> memberCoupons = couponMapper.getMemberCoupons(1);
				if (memberCoupons.size() > 0) {
				    List<Map<String, Object>> receivableIdList = new ArrayList<>();
				    for (Coupon memberCoupon : memberCoupons) {
				        HashMap<String, Object> map = new HashMap<>();
				        map.put("wxUid", wxUid);
				        map.put("couponId", memberCoupon.getId());
				        map.put("tradeType", order.get("trade_type"));
				        receivableIdList.add(map);
				    }
				    couponMapper.createCouponUser(receivableIdList);
				}
			} catch (Exception e) {
				log.error("会员优惠增加失败");
			}

		} catch (Exception e) {
			log.error("接收微信支付结果通知error", e);
			resultMap.put("return_code", "FAIL");
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
		}
		try {
			resXml = WXPayUtil.mapToXml(resultMap);
		} catch (Exception e) {
			log.error("接收微信支付结果通知error", e);
		}
		log.info("接收微信支付结果通知-结束-{}", resXml);
		return resXml;
	}

	@Override
	public ResponseForm orderQuery(RequestForm param) {
		log.info("查询订单 - 开始");
		ResponseForm result = new ResponseForm();
		Map<String, Object> paramMap = (Map<String, Object>) param.getData();
		String orderId = null;
		Map<String, String> map = null;
		try {
			// 调用微信支付查询订单
			log.debug("调用微信支付查询订单");
			orderId = String.valueOf(paramMap.get("orderId"));
			String tradeType = String.valueOf(paramMap.get("tradeType"));

			Map<String, Object> payOrderByOrderId = payMapper.getPayOrderByOrderId(orderId);
			paramMap.put("transaction_id", payOrderByOrderId.get("transaction_id"));
			paramMap.put("out_trade_no", payOrderByOrderId.get("id"));
			if ("JSAPI".equals(tradeType)) {
				map = wxpayHandler.orderQuery(paramMap);
			} else if ("APP".equals(tradeType)) {
				map = wxpayHandlerAPP.orderQuery(paramMap);
			}
			log.debug("微信支付查询订单返回:{}", map.toString());

			result.setData(map);
		} catch (Exception e) {
			result.setStatus(false);
			result.setMessage(LogInfo.ERROR);
			log.error("查询订单error,orderId=" + orderId, e);
		}
		return result;
	}

	private void restoreGoodsStock(String orderId) {
		List<Map<String, Object>> detailList = orderMapper.getOrderDetailListByOrderId(orderId);
		for (Map<String, Object> detail : detailList) {
			int goodsId = (int) detail.get("goods_id");
			String specsName = (String) detail.get("specs_name");
			int goodsNum = (int) detail.get("goods_num");

			// 查询库存
			GoodsStock goodsStock = new GoodsStock();
			goodsStock.setGoodsId(goodsId);
			goodsStock.setSpecsName(specsName);
			List<GoodsStock> goodsStocks = goodsStockMapper.select(goodsStock);
			Integer stockNum = goodsStocks.get(0).getStockNum();

			// 更新商品库存
			goodsStock.setStockNum(stockNum + goodsNum);
			Example example = new Example(GoodsStock.class);
			Criteria criteria = example.createCriteria();
			criteria.andEqualTo("goodsId", goodsId);
			criteria.andEqualTo("specsName", specsName);
			goodsStockMapper.updateByExampleSelective(goodsStock, example);
		}
	}

	private String yuan2fen(String amount) {
		String currency = amount.replaceAll("[$￥,]", "");
		int index = currency.indexOf(".");
		int length = currency.length();
		Long amLong;
		if (index == -1) {
			amLong = Long.valueOf(currency + "00");
		} else if (length - index >= 3) {
			amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
		} else if (length - index == 2) {
			amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
		} else {
			amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
		}
		return amLong.toString();
	}

}
